;.386p
P486
SMART
MODEL FLAT


;_DATA SEGMENT DWORD PUBLIC 'DATA'
.DATA

;-------------------INTERUPT VARIABLES-------------------------
sav_DS                dw 1 dup (0)   ;Save ds for this code
sav_WDTIMERINT_seg    dd 1 dup (0)   ;segment of 08 interupt.
sav_WDTIMERINT_ofs    dd 1 dup (0)   ;offset  of 08 interupt.
;--------------------------------------------------------------

;-------------------GENERAL VARIABLES-------------------------
i_active      DB 1 dup (0) ;Flag for telling if the interupt handler 
						   ;is active
;--------------------------------------------------------------

;------------------GLOBAL VARIABLES---------------------------
 _g_wdogtimeroff DB 1 dup (0)  ;The watch dog timer switch;
 _g_wdogtimersec DD 1 dup (0)  ;The watch dog timer one second alert
 _g_wdogtimertrg DD 1 dup (0)  ;The watch dog timer trigger
;--------------------------------------------------------------
;_DATA	ENDS

;_TEXT SEGMENT BYTE PUBLIC 'CODE'
.CODE

;ASSUME	cs:_TEXT, ds:_DATA

;-------------------EXTERNAL JUNK------------------------------
PUBLIC _g_wdogtimersec
PUBLIC _g_wdogtimeroff
PUBLIC _g_wdogtimertrg

PUBLIC FWWdogtimer_Driver_
PUBLIC FWWdogtimer_InstallDriver_
PUBLIC FWWdogtimer_DestallDriver_

;i_active      DB 1 dup (0) ;Flag for telling if the interupt handler 
                            ;is active
;
;  Gets the location of interupt 08, (timer interupt).
;
FWWdogtimer_get_08_info_ proc
     push es
     push eax
     push ebx

	 mov ax,3508h                  ;Set up to get int 08 loc
	 int 21h                       ;Get it

	 mov ax,es                     ;Twiddle es to 32 bits
	 movzx eax,ax

	 mov dword ptr sav_WDTIMERINT_seg,eax  ;Save the information
	 mov dword ptr sav_WDTIMERINT_ofs,ebx  
	 mov  word ptr sav_DS,ds       ;Save ds

	 pop  ebx
	 pop  eax
	 pop  es
	 ret
FWWdogtimer_get_08_info_ endp

;
;  Reset the location of interupt 08, the timer interupt.
;
FWWdogtimer_InstallDriver_ proc
     push ds
     push eax
     push ecx
     push edx

	 mov _g_wdogtimersec,0
	 mov _g_wdogtimertrg,0
	 mov _g_wdogtimeroff,0
     call FWWdogtimer_get_08_info_

     ;Now reset the interupt.
     mov cx,cs
	 mov ds,cx
	 mov edx, offset FWWdogtimer_Driver_
     mov ax,2508h
	 int 21h

	 pop  edx
	 pop  ecx
	 pop  eax
	 pop  ds
	 ret
FWWdogtimer_InstallDriver_ endp

FWWdogtimer_Driver_ proc
    push ds              ;Ordinary save crap
	push es
    push eax

;-----------------THESE THINGS WILL BE POPPED OF DURING THE INTERUPT CALL
    pushf                ;Save the flags register for the imminent return from
	                     ;08 interupt call
    push ds              ;These things are dummys. Used to save return 
	push es              ;address to the timer code

    push ds              ;These two top things are dummys
	push es              ;used to store return address to real interrupt
 	                     ;code.
;--------------------------------------------------------------
    mov ax,cs
	mov ds,ax
	mov ds,sav_DS
	mov es,sav_DS

	mov eax,sav_WDTIMERINT_ofs
	mov es, sav_WDTIMERINT_seg

	;Load the address of the realinterupt code onto stack
	mov [esp + 00h],eax 
	mov [esp + 04h],es

	;Load the address of the timer code onto stack, flags already below
	;The real interupt will pop these off the stack when it comes back
	mov eax, offset wdogtimer_code
	mov [esp + 08h], eax
	mov ax,cs
	movzx eax,ax
	mov [esp + 0Ch], eax
	                  ;Flags already below.
	retf              ;Jump to real timer code

    mov ax,cs
	mov ds,ax
	mov ds,sav_DS
	mov es,sav_DS

wdogtimer_code:    ;Timer interupt returns here
    cmp i_active,1
	je prevent_recursion

    cmp _g_wdogtimertrg,1
	je prevent_recursion

    cmp _g_wdogtimeroff,1
	je prevent_recursion

	mov i_active,1
	inc _g_wdogtimersec
    cmp _g_wdogtimersec,200
	jnz leave_driver

	mov _g_wdogtimersec,0
	mov _g_wdogtimertrg,1

 leave_driver:
	mov i_active,0

prevent_recursion:
	pop eax
	pop es
    pop ds
	iret         ;Must do an iret because we have to return from an interupt 
	             ;call ourselves, ie the flags register must be popped off
				 ;as well.
FWWdogtimer_Driver_ endp

;
;  Reset the location of interupt 08, the timer interupt
;  back to its original value
;
FWWdogtimer_DestallDriver_ proc
     cli 
     push ds
     push eax
     push edx
	 
     mov edx, sav_WDTIMERINT_ofs
	 mov ds,  sav_WDTIMERINT_seg
     mov ax,2508h
	 sti
	 int 21h

	 pop  edx
	 pop  eax
	 pop  ds
	 ret
FWWdogtimer_DestallDriver_ endp

;_TEXT ENDS
END
